/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "napi_x509_cert_match_parameters.h"

#include "cf_log.h"
#include "cf_memory.h"
#include "cf_object_base.h"
#include "cf_result.h"
#include "cf_type.h"
#include "napi/native_api.h"
#include "napi/native_node_api.h"
#include "napi_cert_defines.h"
#include "napi_cert_utils.h"
#include "napi_object.h"
#include "utils.h"

namespace OHOS {
namespace CertFramework {

static napi_value GetSubjectAltNames(napi_env env, napi_value arg, SubjectAlternaiveNameArray *&param)
{
    napi_value obj;
    napi_status status = napi_get_named_property(env, arg, CERT_MATCH_TAG_SUBJECT_ALT_NAMES.c_str(), &obj);
    if (status != napi_ok) {
        LOGE("get property failed!");
        return nullptr;
    }
    bool flag = false;
    status = napi_is_arraybuffer(env, obj, &flag);
    if (status != napi_ok || !flag) {
        LOGE("not array!");
        return nullptr;
    }
    uint32_t length;
    status = napi_get_array_length(env, obj, &length);
    if (status != napi_ok || length == 0) {
        LOGE("array length = 0!");
        return nullptr;
    }
    param = (SubjectAlternaiveNameArray *)HcfMalloc(sizeof(SubjectAlternaiveNameArray), 0);
    param->count = length;
    param->data = (SubjectAlternaiveNameData *)HcfMalloc(length * sizeof(SubjectAlternaiveNameData), 0);
    for (uint32_t i = 0; i < length; i++) {
        napi_value element;
        status = napi_get_element(env, obj, i, &element);
        if (status != napi_ok) {
            continue;
        }
        {
            napi_value subObj;
            napi_status status =
                napi_get_named_property(env, element, CERT_MATCH_TAG_SUBJECT_ALT_NAMES_TYPE.c_str(), &subObj);
            if (status != napi_ok) {
                LOGE("get property failed!");
                continue;
            }
            // napi_get_value_uint32(env, format, reinterpret_cast<uint32_t *>(&(param->data[i]->type)));
        }
        {
            napi_value subObj;
            napi_status status =
                napi_get_named_property(env, element, CERT_MATCH_TAG_SUBJECT_ALT_NAMES_DATA.c_str(), &subObj);
            if (status != napi_ok) {
                LOGE("get property failed!");
                continue;
            }
        }
    }
    return nullptr;
}

napi_value BuildX509CertMatchParams(napi_env env, napi_value arg, HcfX509CertMatchParams *&matchParams)
{
    napi_valuetype type;
    napi_typeof(env, arg, &type);
    if (type != napi_object) {
        napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "param type is not object"));
        LOGE("wrong argument type. expect string type. [Type]: %d", type);
        return nullptr;
    }
    GetSubjectAltNames(env, arg, matchParams->subjectAlternativeNames);
    return nullptr;
}

void FreeX509CertMatchParams(HcfX509CertMatchParams *&matchParams)
{
    if (!matchParams) {
        return;
    }

    CfBlobDataFree(matchParams->validDate);
    CfBlobDataFree(matchParams->issuer);
    CfBlobDataFree(matchParams->keyUsage);
    CfBlobDataFree(matchParams->nameConstraint);
    CfBlobDataFree(matchParams->privateKeyValid);
    CfBlobDataFree(matchParams->serialNumber);
    CfBlobDataFree(matchParams->subject);
    CfBlobDataFree(matchParams->subjectKeyIdentifier);
    CfBlobDataFree(matchParams->publicKey);
    CfBlobDataFree(matchParams->publicKeyAlgID);
    if (matchParams->extendedKeyUsage) {
        FreeCfBlobArray(matchParams->extendedKeyUsage->data, matchParams->extendedKeyUsage->count);
    }
    if (matchParams->certPolicy) {
        FreeCfBlobArray(matchParams->certPolicy->data, matchParams->certPolicy->count);
    }
    CfFree(matchParams);
    matchParams = nullptr;
}

} // namespace CertFramework
} // namespace OHOS